"""
    定义一个函数
"""
def add(a,b):
    return a+b

#调用函数，传入实际参数
sum = add(3,4)
print(sum)

"""
    id()查看地址

    由此可见python在调用函数时传入了实际参数本身
"""
def get_id(params):
    print("参数地址为",id(params))
    return id(params)

a = 5
print("a的地址为",id(a))
a_id = get_id(a)
print(a_id==id(a))

listA = [1,2,3]
print("listA的地址为",id(listA))
listA_id = get_id(listA)
print(listA_id==id(listA))



"""
    参数:位置参数

    调用函数时的实际参数个数必须和形式参数一样
"""
def get_sum(a,b,c):
    return a+b+c 

print(get_sum(5,6,7))

"""
    参数
    关键字参数
"""
def get_str(name,str):
    return str+" "+name 

# 传参顺序可以与形参顺序不一样
print(get_str(str='hello',name='upsilon'))

"""
    参数
    默认参数

    传递参数时如果没有接到实际参数，则会使用默认参数
"""
def get_age(age=18):
    return age 

print(get_age())

"""
    参数
    不定长参数

    *形参名 该形参会以元组形式接收所有的实际参数
    **形参名 该形参会以字典的形式接收所有的实际参数

    *形参 后如果还出现其他形参，只能采用关键字传递
"""

def get_tuple(a,*val):
    print(a)
    print(val)

# 5 (6,7,8)
get_tuple(5,6,7,8)

def get_dict(a,**val):
    print(a)
    print(val)

"""
    由于**val会把多余的实参变成dict形式

    所以多余实参必须传入 键=值 的形式
"""
# 错误示范
# get_dict("a","b","c")

# 正确示例
# a {'b': 100, 'c': 50}
get_dict("a",b=100,c=50)

"""
    星号单独出现，后面所有形参必须用关键字传参
"""
def get_num(a,*,b):
    print(a)
    print(b)

"""
    错误示范：报错提示参数缺失
    Traceback (most recent call last):
    ...
    TypeError: get_num() missing 1 required keyword-only argument: 'b'
"""
# get_num(10)


"""
    错误示范:报错提示多余的位置参数
    Traceback (most recent call last):
    ...
    TypeError: get_num() takes 1 positional argument but 2 were given
"""
# get_num(10,20)

get_num(10,b=25)

"""
    参数
    强制位置参数
"""
def get_val(a,b,/,c,d):
    pass 

"""
    /前的参数只能使用位置参数，不能使用关键字参数
    Traceback (most recent call last):
    ...
    TypeError: get_val() got some positional-only arguments passed as keyword arguments: 'a, b'
"""
# get_val(a=50,b=20,c=30,d=40)

get_val(20,30,40,50)

"""
    return语句
"""
def return_test(a,b):
    a = a+10
    b=b+10
    return a 
    # 后面的语句不再执行
    a = a-5

print(return_test(10,20))